; ACL2 books on arithmetic
; Copyright (C) 1997  Computational Logic, Inc.

; This book is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 2 of the License, or
; (at your option) any later version.

; This book is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
; GNU General Public License for more details.

; You should have received a copy of the GNU General Public License
; along with this book; if not, write to the Free Software
; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

; Written by:
; Matt Kaufmann, Bishop Brock, and John Cowles, with help from Art Flatau
; Computational Logic, Inc.
; 1717 West Sixth Street, Suite 290
; Austin, TX 78703-4776 U.S.A.

(in-package "ACL2")

; The following book of John Cowles should be included before certifying
; the present book.

#|
(DEFPKG "ACL2-ASG"
  (SET-DIFFERENCE-EQUAL
   (UNION-EQ *ACL2-EXPORTS* *COMMON-LISP-SYMBOLS-FROM-MAIN-LISP-PACKAGE*)
   '(ZERO)))
(DEFPKG "ACL2-CRG"
  (SET-DIFFERENCE-EQUAL
   (UNION-EQ *ACL2-EXPORTS* *COMMON-LISP-SYMBOLS-FROM-MAIN-LISP-PACKAGE*)
   '(ZERO)))
(DEFPKG "ACL2-AGP"
  (SET-DIFFERENCE-EQUAL
   (UNION-EQ *ACL2-EXPORTS* *COMMON-LISP-SYMBOLS-FROM-MAIN-LISP-PACKAGE*)
   '(ZERO)))

Then:
(certify-book "rationals-equalities" 3 nil)
|#

#-:non-standard-analysis
(defmacro real-listp (l)
  `(rational-listp ,l))

(include-book "../cowles/acl2-crg" :load-compiled-file nil)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Force
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; It's tempting to force all acl2-numberp hypotheses, and the like.
; Since this is a rather new thing to do, let write a macro for force
; that we can easily change if we want to.

#|
(defmacro fc (x)
  (list 'force x))
|#

; Or, since in this version we want to try this without forcing:
(defmacro fc (x)
  x)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Facts about + (and -)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defthm commutativity-2-of-+
  (equal (+ x (+ y z))
         (+ y (+ x z))))

(defthm functional-self-inversion-of-minus
  (equal (- (- x))
         (fix x)))

(defthm distributivity-of-minus-over-+
  (equal (- (+ x y))
         (+ (- x) (- y))))

(defthm minus-cancellation-on-right
  (equal (+ x y (- x))
         (fix y)))

(defthm minus-cancellation-on-left
  (equal (+ x (- x) y)
         (fix y)))

; Note that the cancellation rules below (and similarly for *) aren't
; complete, in the sense that the element to cancel could be on the
; left side of one expression and the right side of the other.  But
; perhaps those situations rarely arise in practice.  (?)

(defthm right-cancellation-for-+
  (equal (equal (+ x z)
                (+ y z))
         (equal (fix x) (fix y))))

(defthm left-cancellation-for-+
  (equal (equal (+ x y)
                (+ x z))
         (equal (fix y) (fix z))))

(defthm equal-minus-0
  (equal (equal 0 (- x))
         (equal 0 (fix x))))

(defthm inverse-of-+-as=0
  (equal (equal (- a b) 0)
         (equal (fix a) (fix b))))

(defthm equal-minus-minus
  (equal (equal (- a) (- b))
         (equal (fix a) (fix b))))

(defthm fold-consts-in-+
  (implies (and (syntaxp (quotep x))
		(syntaxp (quotep y)))
	   (equal (+ x (+ y z))
		  (+ (+ x y) z))))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Facts about * (and /)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; The same as Inverse-of-*, from axioms.lisp, but with force.
#|
(defaxiom right-inverse-of-*
  (implies (and (acl2-numberp x)
                (not (equal x 0)))
           (equal (* x (/ x)) 1)))
|#

#| The following proof of commutativity-2-of-* was originally obtained by using
   John Cowles's macro acl2-asg::add-commutativity-2 as follows, and
   then editing out package references in the statement of the final
   theorem.
(acl2-asg::add-commutativity-2 equal
			       acl2-numberp 
			       * 
			       commutativity-of-*
			       commutativity-2-of-*)
|#

(defthm commutativity-2-of-*
   (equal (* x (* y z))
          (* y (* x z)))
   :hints
   (("Goal"
     :use
     (:instance
      (:functional-instance
       acl2-asg::commutativity-2-of-op
       (acl2-asg::equiv equal)
       (acl2-asg::pred (lambda (x) t))
       (acl2-asg::op binary-*))
      (acl2-asg::x x)
      (acl2-asg::y y)
      (acl2-asg::z z)))))

(defthm functional-self-inversion-of-/
  (equal (/ (/ x)) (fix x))
  :hints (("Goal"
	   :use
           ((:instance
             (:functional-instance
              acl2-agp::Involution-of-inv
              (acl2-agp::equiv equal)
              (acl2-agp::pred (lambda 
                                (x) 
                                (and (acl2-numberp x)
                                     (not (equal x 0)))))
              (acl2-agp::op binary-*)
              (acl2-agp::id (lambda () 1))
              (acl2-agp::inv unary-/))
             (acl2-agp::x x))))))

(defthm distributivity-of-/-over-*
  (equal (/ (* x y))
	 (* (/ x) (/ y)))
  :hints (("Goal"
	   :use ((:instance
                  (:functional-instance
                   acl2-agp::Distributivity-of-inv-over-op
                   (acl2-agp::equiv equal)
                   (acl2-agp::pred (lambda 
                                     (x)
                                     (and (acl2-numberp x)
                                          (not (equal x 0)))))
                   (acl2-agp::op binary-*)
                   (acl2-agp::id (lambda () 1))
                   (acl2-agp::inv unary-/))
                  (acl2-agp::x x)
                  (acl2-agp::y y))))))

(defthm /-cancellation-on-right
  (implies (and (fc (acl2-numberp x))
		(fc (not (equal x 0))))
	   (equal (* x y (/ x))
		  (fix y)))
  :hints (("Goal"
	   :use
           ((:instance
             (:functional-instance
              acl2-agp::inv-cancellation-on-right
              (acl2-agp::equiv equal)
              (acl2-agp::pred (lambda 
                                (x) 
                                (and (acl2-numberp x)
                                     (not (equal x 0)))))
              (acl2-agp::op binary-*)
              (acl2-agp::id (lambda () 1))
              (acl2-agp::inv unary-/))
             (acl2-agp::x x)
             (acl2-agp::y y))))))

(defthm /-cancellation-on-left
  (implies (and (fc (acl2-numberp x))
                (fc (not (equal 0 x))))
           (equal (* x (/ x) y)
                  (fix y)))
  :hints (("Goal" :use /-cancellation-on-right)))

(encapsulate
 ()

 (local
  (defthm right-cancellation-for-*-lemma
    (implies (and (equal (* x z) (* y z))
                  (acl2-numberp z)
                  (not (equal 0 z))
                  (acl2-numberp x)
                  (acl2-numberp y))
             (equal (equal x y) t))
    :hints (("Goal" :use
             ((:instance
               (:functional-instance
                acl2-agp::Right-cancellation-for-op
                (acl2-agp::equiv equal)
                (acl2-agp::pred (lambda 
                                  (x) 
                                  (and (acl2-numberp x)
                                       (not (equal x 0)))))
                (acl2-agp::op binary-*)
                (acl2-agp::id (lambda () 1))
                (acl2-agp::inv unary-/))
               (acl2-agp::x x)
               (acl2-agp::y y)
               (acl2-agp::z z)))))))

 (defthm right-cancellation-for-*
   (equal (equal (* x z) (* y z))
          (or (equal 0 (fix z))
              (equal (fix x) (fix y))))))

(defthm left-cancellation-for-*
  (equal (equal (* z x) (* z y))
         (or (equal 0 (fix z))
             (equal (fix x) (fix y)))))

(defthm
  Zero-is-only-zero-divisor
  (equal (equal (* x y) 0)
         (or (equal (fix x) 0)
             (equal (fix y) 0))))

(defthm equal-*-x-y-x
  (equal (equal (* x y) x)
         (or (equal x 0)
             (and (equal y 1)
                  (acl2-numberp x))))
  :hints (("Goal" :use
           ((:instance right-cancellation-for-*
                       (z x)
                       (x y)
                       (y 1))))))

(defthm equal-*-x-y-y
  (equal (equal (* x y) y)
         (or (equal y 0)
             (and (equal x 1)
                  (acl2-numberp y))))
  :hints (("Goal" :use
           ((:instance right-cancellation-for-*
                       (z y)
                       (x x)
                       (y 1))))))

(encapsulate
 ()

 (local
  (defthm equal-/-lemma
    (implies (and (acl2-numberp x)
                  (acl2-numberp y)
                  (equal (* x y) 1))
             (equal y (/ x)))
    :rule-classes nil 
    :hints (("Goal"
             :use
             (:instance
              (:functional-instance
               acl2-agp::Uniqueness-of-op-inverses
               (acl2-agp::equiv equal)
               (acl2-agp::pred (lambda 
                                 (x) 
                                 (and (acl2-numberp x)
                                      (not (equal x 0)))))
               (acl2-agp::op binary-*)
               (acl2-agp::id (lambda () 1))
               (acl2-agp::inv unary-/))
              (acl2-agp::x x)
              (acl2-agp::y y))))))

 (defthm equal-/
   (implies (and (fc (acl2-numberp x))
                 (fc (not (equal 0 x))))
            (equal (equal (/ x) y)
                   (equal 1 (* x y))))
   :hints (("Goal" :use equal-/-lemma)))
 )

; The following hack helps in the application of equal-/ when forcing is
; turned off.

(defthm numerator-nonzero-forward
  (implies (not (equal (numerator r) 0))
           (and (not (equal r 0))
                (acl2-numberp r)))
  :rule-classes
  ((:forward-chaining :trigger-terms
                      ((numerator r)))))

; The following loops with the lemma equal-/ just proved but is
; sometimes useful.

(encapsulate
 ()

 (local
  (defthm Uniqueness-of-*-inverses-lemma
    (equal (equal (* x y)
                  1)
           (and (not (equal x 0))
                (acl2-numberp x)
                (equal y (/ x))))))

 (defthm Uniqueness-of-*-inverses
   (equal (equal (* x y)
                 1)
          (and (not (equal (fix x) 0))
               (equal y (/ x))))
   :hints (("Goal" :in-theory (disable equal-/)))))

(in-theory (disable Uniqueness-of-*-inverses))

(theory-invariant
 (not (and (active-runep '(:rewrite Uniqueness-of-*-inverses))
           (active-runep '(:rewrite equal-/)))))

(encapsulate
 ()

 (local
  (defthm equal-/-/-lemma
    (implies
     (and (fc (acl2-numberp a))
          (fc (acl2-numberp b))
          (fc (not (equal a 0)))
          (fc (not (equal b 0))))
     (equal (equal (/ a) (/ b))
            (equal a b)))
    :hints
    (("Goal"
      :use ((:instance
             (:theorem
              (implies
               (and (fc (acl2-numberp a))
                    (fc (acl2-numberp b))
                    (fc (not (equal a 0)))
                    (fc (not (equal b 0))))
               (implies (equal a b)
                        (equal (/ a) (/ b)))))
             (a (/ a)) (b (/ b))))))
    :rule-classes nil))

 (defthm equal-/-/
   (equal (equal (/ a) (/ b))
          (equal (fix a) (fix b)))
   :hints (("Goal" :use equal-/-/-lemma
                   :in-theory (disable equal-/)))))

(defthm equal-*-/-1
   (implies (and (acl2-numberp x)
                 (not (equal x 0)))
            (equal (equal (* (/ x) y) z)
                   (and (acl2-numberp z)
                        (equal (fix y) (* x z))))))

(defthm equal-*-/-2
   (implies (and (acl2-numberp x)
                 (not (equal x 0)))
            (equal (equal (* y (/ x)) z)
                   (and (acl2-numberp z)
                        (equal (fix y) (* z x))))))

(defthm fold-consts-in-*
  (implies (and (syntaxp (quotep x))
		(syntaxp (quotep y)))
	   (equal (* x (* y z))
		  (* (* x y) z))))

(defthm times-zero
  ;; We could prove an analogous rule about non-numeric coefficients, but
  ;; this one has efficiency advantages:  it doesn't match too often, it has
  ;; no hypothesis, and also we know that the 0 is the first argument so we
  ;; don't need two versions.  Besides, we won't need this too often; it's
  ;; a type-reasoning fact.  But it did seem useful in the proof of a meta
  ;; lemma about times cancellation, so we include it here.
  (equal (* 0 x) 0))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Facts about + (or -) and * (or /) together
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(encapsulate
 ()
 
 (local
  (defthm functional-commutativity-of-minus-*-right-lemma
    (implies (and (fc (acl2-numberp x))
                  (fc (acl2-numberp y)))
             (equal (* x (- y))
                    (- (* x y))))
    :hints (("Goal"
             :use
             ((:instance
               (:functional-instance
                acl2-crg::functional-commutativity-of-minus-times-right
                (acl2-crg::equiv equal)
                (acl2-crg::pred acl2-numberp)
                (acl2-crg::plus binary-+)
                (acl2-crg::times binary-*)
                (acl2-crg::zero (lambda () 0))
                (acl2-crg::minus unary--))
               (acl2-crg::x x)
               (acl2-crg::y y)))))
    :rule-classes nil))

 (defthm functional-commutativity-of-minus-*-right
   (equal (* x (- y))
          (- (* x y)))
   :hints (("Goal" :use functional-commutativity-of-minus-*-right-lemma))))

(defthm functional-commutativity-of-minus-*-left
  (equal (* (- x) y)
         (- (* x y))))

(defthm reciprocal-minus
  (equal (/ (- x))
         (- (/ x)))
  :hints (("Goal" :cases
           ((and (fc (acl2-numberp x))
                 (fc (not (equal x 0))))))))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Facts about numerator and denominator
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(encapsulate
 ()

 (local
  (defthm numerator-integerp-lemma-1
    (implies (rationalp x)
             (equal (* (* (numerator x) (/ (denominator x))) (denominator x))
                    (numerator x)))
    :rule-classes nil
    :hints (("Goal" :in-theory (disable rational-implies2)))))

 (local
  (defthm numerator-integerp-lemma
    (implies (and (rationalp x)
                  (equal (* (numerator x) (/ (denominator x)))
                         x))
             (equal (numerator x)
                    (* x (denominator x))))
    :rule-classes nil
    :hints (("Goal" :use (numerator-integerp-lemma-1)
             :in-theory (disable rational-implies2)))))

 (defthm numerator-when-integerp
   (implies (integerp x)
            (equal (numerator x)
                   x))
   :hints (("Goal" :in-theory (disable rational-implies2)
            :use ((:instance lowest-terms (r x)
                             (q 1)
                             (n (denominator x)))
                  rational-implies2
                  numerator-integerp-lemma))))
 )

(defthm integerp==>denominator=1
  (implies (integerp x)
           (equal (denominator x) 1))
  :hints
  (("Goal"
    :use (rational-implies2 numerator-when-integerp)
    :in-theory (disable rational-implies2))))

(defthm equal-denominator-1
  (equal (equal (denominator x) 1)
         (or (integerp x)
             (not (rationalp x))))
  :hints (("Goal" :use (rational-implies2 completion-of-denominator)
           :in-theory (disable rational-implies2))))

(defthm *-r-denominator-r
  (equal (* r (denominator r))
         (if (rationalp r)
             (numerator r)
           (fix r)))
  :hints (("Goal" :use ((:instance rational-implies2 (x r)))
           :in-theory (disable rational-implies2))))

(defthm /r-when-abs-numerator=1
  (and
   (implies
    (equal (numerator r) 1)
    (equal (/ r) (denominator r)))
   (implies
    (equal (numerator r) -1)
    (equal (/ r) (- (denominator r)))))
  :hints (("Goal" :use ((:instance rational-implies2 (x r)))
           :in-theory (disable rational-implies2))))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Facts about expt
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; Much of this is adapted from John Cowles's acl2-exp.lisp book.
; There are various modifications, however, including some by
; Ruben Gamboa to support non-standard analysis in the non-standard
; version of ACL2, ACL2(r); see :doc real.

#+:non-standard-analysis
(defthm expt-type-prescription-realp
  (implies (realp r)
           (realp (expt r i)))
  :rule-classes (:type-prescription :generalize))

(defthm expt-type-prescription-rationalp
  (implies (rationalp r)
           (rationalp (expt r i)))
  :rule-classes (:type-prescription :generalize))

;; This theorem was strengthened to allow all real numbers (but reduces to
;; the version with a rationalp hypothesis in for ACL2, as opposed to ACL2(r)).

(defthm expt-type-prescription-positive
  (implies (and (< 0 r)
                (real/rationalp r))
           (< 0 (expt r i)))
  :rule-classes (:type-prescription :generalize))

(defthm expt-type-prescription-nonzero
  (implies (and (fc (acl2-numberp r))
                (not (equal r 0)))
           (not (equal 0 (expt r i))))
  :rule-classes (:type-prescription :generalize))

(defthm expt-type-prescription-integerp
  (implies (and (<= 0 i)
                (integerp r))
           (integerp (expt r i)))
  :rule-classes (:type-prescription :generalize))

(defthm Left-nullity-of-1-for-expt
  (equal (expt 1 i) 1))

(defthm Right-unicity-of-1-for-expt
  (equal (expt r 1)
         (fix r))
  :hints (("Goal" :expand (expt r 1))))

(defthm expt-minus
  (equal (expt r (- i))
         (/ (expt r i))))

; The following is superseded by exponents-add below, except for the
; case that r = 0.  But I'll leave it here; in fact it's quite natural
; to have (roughly speaking) two versions of each rule about expt,
; based on the disjunction in the guard for expt.

(defthm Exponents-add-for-nonneg-exponents

; We don't need that r is non-zero for this one.

  (implies (and (<= 0 i)
                (<= 0 j)
                (fc (integerp i))
                (fc (integerp j)))
           (equal (expt r (+ i j))
                  (* (expt r i)
                     (expt r j)))))

(encapsulate
 ()

 (local
  (defthm Exponents-add-negative-negative
    (implies (and (integerp i)
                  (integerp j)
                  (< i 0)
                  (< j 0))
             (equal (expt r (+ i j))
                    (* (expt r i)
                       (expt r j))))
    :rule-classes nil))

 (local
  (defthm Exponents-add-positive-negative
    (implies (and (integerp i)
                  (integerp j)
                  (acl2-numberp r)
                  (not (equal r 0))
                  (< 0 i)
                  (< j 0))
             (equal (expt r (+ i j))
                    (* (expt r i)
                       (expt r j))))
    :hints (("Goal" :expand (expt r (+ i j))))
    :rule-classes nil))

 (defthm Exponents-add

; The first two (syntaxp) hypotheses below are new for Version_2.6.  Without
; this change there can be looping with the definition of expt, for example on
; the following (thanks to Eric Smith for reporting the problem from which this
; example was culled).  (By the way, this example is probably not a theorem;
; the point here is to avoid looping.)  But see also
; Exponents-add-unrestricted.

  #|
   (thm (IMPLIES (AND (NOT (ZIP P))
                      (< 0 P)
                      (< (* 2 (+ P -1) (/ (EXPT 2 (+ P -1))))
                         1)
                      (INTEGERP P)
                      (< 1 P)
                      (INTEGERP Q)
                      (< 0 Q))
                 (< (* 2 P (/ (EXPT 2 P))) 1)))
  |#

   (implies (and (syntaxp (not (and (quotep i) (integerp (cadr i))
                                    (or (equal (cadr i) 1)
                                        (equal (cadr i) -1)))))
                 (syntaxp (not (and (quotep j) (integerp (cadr j))
                                    (or (equal (cadr j) 1)
                                        (equal (cadr j) -1)))))
                 (not (equal 0 r))
                 (fc (acl2-numberp r))
                 (fc (integerp i))
                 (fc (integerp j)))
            (equal (expt r (+ i j))
                   (* (expt r i)
                      (expt r j))))
   :hints (("Goal" :use
            (Exponents-add-negative-negative
             Exponents-add-positive-negative
             (:instance Exponents-add-positive-negative
                        (i j) (j i)))))))

(defthm Exponents-add-unrestricted

; The comment above in Exponents-add explains why we do not leave this rule
; enabled.  But we include it in case it is of use.  For example, Exponents-add
; is not sufficient for the proof of expt-is-increasing-for-base>1 in
; inequalities.lisp.

   (implies (and (not (equal 0 r))
                 (fc (acl2-numberp r))
                 (fc (integerp i))
                 (fc (integerp j)))
            (equal (expt r (+ i j))
                   (* (expt r i)
                      (expt r j)))))

(in-theory (disable Exponents-add-unrestricted))

(defthm Distributivity-of-expt-over-*
  (equal (expt (* a b) i)
         (* (expt a i)
            (expt b i))))

; It's not clear to me whether the following rule belongs this way
; or the other way around, but I'll leave it this way -- mk.

(defthm expt-1
  (equal (expt 1 x) 1))

(defthm Exponents-multiply
  (implies (and (fc (integerp i))
                (fc (integerp j)))
           (equal (expt (expt r i) j)
                  (expt r (* i j))))
  :hints (("Goal" :cases
           ((not (acl2-numberp r))
            (equal r 0)))))

(defthm Functional-commutativity-of-expt-/-base
  (equal (expt (/ r) i)
         (/ (expt r i))))

; Added 6/01 by Matt Kaufmann in response to an example sent by John Cowles
; that cannot be proved without it, shown below.  Actually this rule was
; suggested by J Moore.
(defthm equal-constant-+
  (implies (syntaxp (and (quotep c1) (quotep c2)))
           (equal (equal (+ c1 x) c2)
                  (if (acl2-numberp c2)
                      (if (acl2-numberp x)
                          (equal x (- c2 c1))
                        (equal (fix c1) c2))
                    nil))))

#| John Cowles's example (see rule above); without the rule above the following
   hint is needed for the thm form below:

;    :hints (("Goal"
;	      :use (:theorem
;		    (implies (equal (+ -1 x) 3)
;			     (equal x 4)))))

   (include-book
     "/meru1/cowles/acl2/ver2.5/acl2-sources/books/arithmetic/top-with-meta")

   (defun  ;; compute 2^n
       pow (n)
     (if (zp n)
	 1
       (* 2 (pow (- n 1)))))

   (defun e (x) ;; product from i=1 to x of 2^i - 1
     (if (zp x)
	 1
       (* (- (pow x) 1)(e (- x 1)))))

   (defun
       e1 (x)
     (if (zp x)
	 1
       (* (pow x)(e1 (- x 1)))))

   (thm
     ;; some complicated hyps removed
     (IMPLIES (EQUAL (+ -1 X) 3)
	      (EQUAL (+ (* 384 (POW (+ -4 X)))
			(- (* 768 (POW (+ -4 X)) (POW (+ -4 X))))
			(* 3456
			   (/ (+ (- (* 2 (E (+ -4 X))
				       (E1 (+ -4 X))
				       (POW (+ -4 X))))
				 (* 4 (E (+ -4 X))
				    (E1 (+ -4 X))
				    (POW (+ -4 X))
				    (POW (+ -4 X)))))))
		     (+ (- (* 64 (E (+ -4 X))
			      (E1 (+ -4 X))
			      (POW (+ -4 X))
			      (POW (+ -4 X))
			      (POW (+ -4 X))))
			(* 128 (E (+ -4 X))
			   (E1 (+ -4 X))
			   (POW (+ -4 X))
			   (POW (+ -4 X))
			   (POW (+ -4 X))
			   (POW (+ -4 X)))
			(* 256 (E (+ -4 X))
			   (E1 (+ -4 X))
			   (POW (+ -4 X))
			   (POW (+ -4 X))
			   (POW (+ -4 X))
			   (POW (+ -4 X)))
			(* 512 (E (+ -4 X))
			   (E1 (+ -4 X))
			   (POW (+ -4 X))
			   (POW (+ -4 X))
			   (POW (+ -4 X))
			   (POW (+ -4 X)))
			(- (* 512 (E (+ -4 X))
			      (E1 (+ -4 X))
			      (POW (+ -4 X))
			      (POW (+ -4 X))
			      (POW (+ -4 X))
			      (POW (+ -4 X))
			      (POW (+ -4 X))))
			(- (* 1024 (E (+ -4 X))
			      (E1 (+ -4 X))
			      (POW (+ -4 X))
			      (POW (+ -4 X))
			      (POW (+ -4 X))
			      (POW (+ -4 X))
			      (POW (+ -4 X))))
			(- (* 2048 (E (+ -4 X))
			      (E1 (+ -4 X))
			      (POW (+ -4 X))
			      (POW (+ -4 X))
			      (POW (+ -4 X))
			      (POW (+ -4 X))
			      (POW (+ -4 X))))
			(* 4096 (E (+ -4 X))
			   (E1 (+ -4 X))
			   (POW (+ -4 X))
			   (POW (+ -4 X))
			   (POW (+ -4 X))
			   (POW (+ -4 X))
			   (POW (+ -4 X))
			   (POW (+ -4 X)))))))

|#
